package top.maof.book.rank;

import cn.hutool.core.util.ObjectUtil;

import java.lang.reflect.Field;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Set;

public interface KeyGenerate<T> {

    default Set<String> generateKeys(T t) throws Exception {

        Field[] fields = t.getClass().getDeclaredFields();

        Set<String> list = new HashSet<>();

        Queue<T> queue = new LinkedList<>();

        queue.offer(t);

        for (int i = 0; i < fields.length; i++) {

            Field field = fields[i];
            field.setAccessible(true);
            // 如果属性标记为ignore,生成key时则跳过该属性
            KeyProperty annotation = field.getDeclaredAnnotation(KeyProperty.class);

            if (annotation != null && annotation.ignore()) continue;

            Object value = field.get(t);

            int size = queue.size();

            while (size > 0) {
                T poll = queue.poll();
                if (value != null) {
                    String s = generateKey(poll);

                    list.add(s);
                    queue.offer(poll);

                    // ObjectUtil.clone参数必须是实现了Coneable接口的,否则就会导致克隆后的对象丢失注解
                    T cloneT = ObjectUtil.clone(poll);

                    Field cloneField = cloneT.getClass().getDeclaredField(field.getName());
                    cloneField.setAccessible(true);

                    cloneField.set(cloneT, null);

                    s = generateKey(cloneT);

                    if (s != null && !"".equals(s)) {
                        list.add(s);
                    }
                    queue.offer(cloneT);
                } else {
                    String s = generateKey(poll);
                    if (s != null && !"".equals(s)) {
                        list.add(s);
                    }
                    queue.offer(poll);
                }
                size--;
            }
        }
        list.add("");
        return filter(list);
    }


    Set<String> filter(Set<String> set);


    default String generateKey(T t) throws Exception {
        Field[] fields = t.getClass().getDeclaredFields();
        StringBuilder sb = new StringBuilder();
        for (Field field : fields) {
            field.setAccessible(true);
            // 如果属性标记为ignore,生成key时则跳过该属性
            KeyProperty annotation = field.getDeclaredAnnotation(KeyProperty.class);
            if (annotation != null && annotation.ignore()) continue;

            String name = field.getName();
            Object value = field.get(t);
            if (value != null) {
                sb.append(name).append(":").append(value).append(":");
            }
        }
        String key = sb.toString();
        if (key != null && key.length() > 0) {
            key = key.substring(0, key.length() - 1);
        } else {
            key = "";
        }
        return key;
    }
}
